package cosc617_blackteam;

import java.awt.*;
import java.awt.event.*;
import java.util.ArrayList;
import java.util.List;
import java.util.Vector;

import javax.swing.*;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;

/**
 * Java swingx UI
 * Implemented using tutorial at
 * http://docs.oracle.com/javase/tutorial/uiswing/components/frame.html
 * http://docs.oracle.com/javase/tutorial/uiswing/components/button.html
 *
 * @author Laura Semesky
 * edited by Anton
 */
public class UserInterface extends JPanel implements ActionListener, ChangeListener, I_Observer {

	private static final long serialVersionUID = 1L;
	protected JButton b1;
	protected JTextArea text;
	protected JSpinner s1, frequencySelect;
	private SystemInterface systemInterface;
	private RestaurantSim sim;
	private int customerID; //will be incremented any time an order is placed.  
	//it will be generated by the appropriate class in the real sim

	public static void createAndShowGUI() {
		JFrame frame = new JFrame("Restaurant User Interface");
		frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

		UserInterface newContentPane = new UserInterface();
		newContentPane.setOpaque(true);
		newContentPane.setPreferredSize(new Dimension(700, 800));
		frame.setContentPane(newContentPane);
		frame.setJMenuBar(newContentPane.createMenuBar());

		//Display the window.
		frame.pack();
		frame.setVisible(true);
	}

	public UserInterface() {

		systemInterface = new SystemInterface();
		//attach observer
		this.systemInterface.attach(this);
		sim = new RestaurantSim(systemInterface);
		//attach observer
		sim.attach(this);
		new Thread(sim).start();
		text = new JTextArea();



		JButton b1 = new JButton("Start Simulation");
		b1.setActionCommand("start");
		b1.addActionListener(this);


		JScrollPane scroll = new JScrollPane(text);
		scroll.setPreferredSize(new Dimension(650, 500));
		scroll.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS);


		add(scroll);
		add(b1);

		b1 = new JButton("Reset Simulation");
		b1.setActionCommand("reset");
		b1.addActionListener(this);
		add(b1);

		frequencySelect = new JSpinner(new SpinnerNumberModel(1, -10, 10, 1));
		add(new JLabel("Customer Frequency"));
		add(frequencySelect);
		frequencySelect.addChangeListener(this);

		// spinner for sleep time
		SpinnerNumberModel numModel = new SpinnerNumberModel(10, 0, 2000, 10);

		s1 = new JSpinner(numModel);
		s1.addChangeListener(this);

		JLabel spinnerLbl = new JLabel("Sleep Duration:");
		spinnerLbl.setLabelFor(s1);
		add(spinnerLbl);
		add(s1);
	}

	public JMenuBar createMenuBar() {
		JMenuBar menuBar = new JMenuBar();


		menuBar.add(createManagerMenu());
		menuBar.add(createCustomerMenu());

		return menuBar;
	}

	private JMenu createCustomerMenu() {
		JMenu menu;
		JMenuItem menuItem;

		menu = new JMenu("Customer");

		menu.add(createMenuSubMenu());

		menuItem = new JMenuItem("Submit Order");
		menu.add(menuItem);
		menuItem.setActionCommand("submitOrder");
		menuItem.addActionListener(this);

		menuItem = new JMenuItem("Submit Comment");
		menu.add(menuItem);
		menuItem.setActionCommand("submitComment");
		menuItem.addActionListener(this);

		menuItem = new JMenuItem("View Approved Comments");
		menu.add(menuItem);
		menuItem.setActionCommand("viewApprovedComments");
		menuItem.addActionListener(this);

		return menu;
	}

	private JMenu createOffersSubMenu(){
		JMenu submenu = new JMenu("Toggle Special Offers");
		for(SpecialOffer offer : SpecialOffer.values()){
			JCheckBoxMenuItem item = new JCheckBoxMenuItem(offer.toString());
			item.setState(offer.isActive());
			submenu.add(item);
			item.setActionCommand(offer.toString());
			item.addActionListener(this);
		}
		return submenu;
	}

	private JMenu createMenuSubMenu() {
		//Display Menu Submenu
		JMenu submenu = new JMenu("Display Menu");

		//Various display menu options in menu submenu
		JMenuItem menuItem = new JMenuItem("Full Menu");

		submenu.add(menuItem);
		menuItem.setActionCommand("getDefaultMenu");
		menuItem.addActionListener(this);

		//Special Attribute Menus
		for (MenuSpecialAttribute value : MenuSpecialAttribute.values()) {
			menuItem = new JMenuItem(value.toString() + " Menu");
			submenu.add(menuItem);
			menuItem.setActionCommand(value.toString());
			menuItem.addActionListener(this);
		}
		return submenu;
	}

	private JMenu createManagerMenu() {
		//Add Manager Pulldown
		JMenu menu, submenu;
		JMenuItem menuItem;



		menu = new JMenu("Manager");

		menu.add(createMenuSubMenu());





		menuItem = new JMenuItem("Add Menu Item");
		menu.add(menuItem);
		menuItem.setActionCommand("newMenuItem");
		menuItem.addActionListener(this);

		menuItem = new JMenuItem("View Orders");
		menu.add(menuItem);
		menuItem.setActionCommand("viewOrders");
		menuItem.addActionListener(this);

		menuItem = new JMenuItem("View Tables");
		menu.add(menuItem);
		menuItem.setActionCommand("viewTables");
		menuItem.addActionListener(this);

		menuItem = new JMenuItem("View Waiting Customers");
		menu.add(menuItem);
		menuItem.setActionCommand("getWaitingCustomers");
		menuItem.addActionListener(this);

		menuItem = new JMenuItem("View Statistics");
		menu.add(menuItem);
		menuItem.setActionCommand("viewStatistics");
		menuItem.addActionListener(this);

		menuItem = new JMenuItem("View Comments");
		menu.add(menuItem);
		menuItem.setActionCommand("viewComments");
		menuItem.addActionListener(this);

		menuItem = new JMenuItem("Approve Comments");
		menu.add(menuItem);
		menuItem.setActionCommand("approveComments");
		menuItem.addActionListener(this);

		menuItem = new JMenuItem("View Tabs");
		menu.add(menuItem);
		menuItem.setActionCommand("viewTabs");
		menuItem.addActionListener(this);

		submenu = this.createOffersSubMenu();
		menu.add(submenu);

		submenu = new JMenu("Set Seating Strategy");
		menu.add(submenu);

		for (SeatingStrategy value : SeatingStrategy.values()) {
			menuItem = new JMenuItem(value + " Seating Strategy"); 
			submenu.add(menuItem);
			menuItem.setActionCommand(value.toString());
			menuItem.addActionListener(this);
		}



		submenu = new JMenu("Set Food Prep Strategy");
		menu.add(submenu);

		for (PrepStrategy value : PrepStrategy.values()){
			menuItem = new JMenuItem(value + " Prep Strategy");
			submenu.add(menuItem);
			menuItem.setActionCommand(value.toString());
			menuItem.addActionListener(this);
		}

		return menu;
	}

	private void addComment() {

		JTextField name = new JTextField();
		JTextField comment = new JTextField();
		//set things to display in optionpane
		JComponent[] inputs = new JComponent[]{new JLabel("Name:"), name, new JLabel("Comment:"), comment};

		//popup
		JOptionPane.showMessageDialog(null, inputs, "Enter Comment", JOptionPane.PLAIN_MESSAGE);
		if (comment.getText().length() == 0) {
			return;
		}
		systemInterface.createComment(name.getText(), comment.getText());


	}

	private boolean doMenuItemOptionPane() {
		JTextField itemName = new JTextField();
		JTextField ingredients = new JTextField();
		JTextField category = new JTextField();
		JTextField price = new JTextField();
		JTextField minutesToCook = new JTextField();
		JList<MenuSpecialAttribute> specialAttributes = new JList<MenuSpecialAttribute>(MenuSpecialAttribute.values());
		specialAttributes.setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION);
		specialAttributes.setLayoutOrientation(JList.VERTICAL);
		JScrollPane sp = new JScrollPane(specialAttributes);
		sp.setPreferredSize(new Dimension(100, 200));

		//everything that should be displayed in the optionpane
		JComponent[] inputs = new JComponent[]{new JLabel("Item Name"), itemName,
				new JLabel("Ingredient List (comma separated)"), ingredients, new JLabel("Category"),
				category, new JLabel("Price"), price, new JLabel("Minutes to cook"), minutesToCook,
				new JLabel("SpecialAttributes"), sp};

		//Popup
		JOptionPane.showMessageDialog(null, inputs, "Enter Menu Item Information", JOptionPane.PLAIN_MESSAGE);

		//copy over selected specialAttributes into new array
		List<MenuSpecialAttribute> list = specialAttributes.getSelectedValuesList();
		MenuSpecialAttribute[] sa = new MenuSpecialAttribute[list.size()];
		for (int i = 0; i < list.size(); i++) {
			sa[i] = (MenuSpecialAttribute) list.get(i);
		}

		//parse ingredients add to array
		String[] ingredientArray = ingredients.getText().split(",");
		ArrayList<String> ingredientAL = new ArrayList<String>();
		for (String ingredient : ingredientArray) {
			ingredientAL.add(ingredient);
		}

		return systemInterface.addMenuItem(itemName.getText(), ingredientAL, category.getText(),
				price.getText(), sa, minutesToCook.getText());

	}

	private String[] getOrders() {

		JList<String> menuItems = new JList<String>(new Vector<String>(systemInterface.getDefaultMenu()));
		menuItems.setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION);
		menuItems.setLayoutOrientation(JList.VERTICAL);
		JScrollPane sp = new JScrollPane(menuItems);
		sp.setPreferredSize(new Dimension(800, 500));
		JComponent[] inputs = new JComponent[]{sp};
		JOptionPane.showMessageDialog(null, inputs, "Select menu items", JOptionPane.PLAIN_MESSAGE);

		String[] a = new String[0];
		return menuItems.getSelectedValuesList().toArray(a);
	}

	private void approveComments(){
		JList<String> comments = new JList<String>(new Vector<String>(systemInterface.getUnapprovedComments()));
		comments.setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION);
		comments.setLayoutOrientation(JList.VERTICAL);
		JScrollPane sp = new JScrollPane(comments);
		sp.setPreferredSize(new Dimension(800, 500));
		JComponent[] inputs = new JComponent[]{sp};
		JOptionPane.showMessageDialog(null, inputs, "Select comments to approve", JOptionPane.PLAIN_MESSAGE);
		String[] a = new String[0];
		systemInterface.approveComments(comments.getSelectedValuesList().toArray(a));
	}

	/* (non-Javadoc)
	 * @see java.awt.event.ActionListener#actionPerformed(java.awt.event.ActionEvent)
	 */
	public void actionPerformed(ActionEvent e) {
		String command = e.getActionCommand();
		switch (command) {

		case "reset":
			sim.setResetSim(true);
			//s1.setValue(50); // I think it's useful to leave this where you set it but if you disagree that's fine
			text.setText("Simulation Reset");
			return;
			//Start Simulation
		case "start":
			//changes button to a pause button
			JButton b = ((JButton) e.getSource());
			b.setActionCommand("stop");
			b.setText("Pause Simulation");
			//text.setText("Simulation Started"); // I see no reason to clear the screen here. I move the text clearing to "reset"
			sim.toggleRunning();

			return;

			//Pause Simulation
		case "stop":
			//changes button to a start button
			b = ((JButton) e.getSource());

			b.setActionCommand("start");
			b.setText("Continue Simulation");
			// text.setText("Simulation Paused"); // I changed it so that "reset" clears the screen so that orders before "stop" remain visible.
			sim.toggleRunning();
			text.setText(text.getText() + "\n\nClock ticks passed: " + sim.getClockTick());

			return;


			//Display Waiting Customers
		case "getWaitingCustomers":
			text.setText("Number of Waiting Parties: "
					+ sim.getWaitingCustomers().size() + "\n\n");
			displayStringArray(sim.getWaitingCustomers());
			return;
			//Display Default Menu
		case "getDefaultMenu":
			text.setText("Full Menu\n\n");
			displayStringArray(systemInterface.getDefaultMenu());
			return;

			//Create New Menu Item
		case "newMenuItem":


			if (doMenuItemOptionPane()) //insert code for SystemInterface.addMenuItem(MenuItem);
			{
				text.setText("Successfully added menu item");
			} else //there was invalid input if null was returned
			{
				text.setText("Error creating menu item");
			}
			return;

			//View Current Orders
		case "viewOrders":
			text.setText("Current Orders\n\n");
			displayStringArray(systemInterface.getOrders());
			return;

			//View Statistics (Total Sales, number of customers served)
		case "viewStatistics":
			text.setText("Statistics\n\n");
			text.append(systemInterface.getStatistics());
			return;

			//View Tabs
		case "viewTabs":
			text.setText("Tabs\n\n");
			displayStringArray(systemInterface.getTabs());
			return;

			//View Current Table Seating
		case "viewTables":
			text.setText("Current Table Seating\n\n");
			displayStringArray(systemInterface.getTables());
			return;


			//Submit Comment
		case "submitComment":
			addComment();
			text.setText("Comment Added\n\n");
			return;

			//View Comments
		case "viewComments":
			text.setText("Customer Comments: \n\n");
			displayStringArray(systemInterface.getComments());
			return;

			//View Approved Comments
		case "viewApprovedComments":
			text.setText("Approved Comments: \n\n");
			displayStringArray(systemInterface.getApprovedComments());
			return;

			//Approve Comments

		case "approveComments":
			approveComments();
			text.setText("Comments Approved \n\n");
			return;

			//Submit Order
		case "submitOrder":
			String[] orders = getOrders();
			text.setText("You Ordered:\n\n");
			for (String s : orders) {
				text.append(s + "\n\n");
			}
			Customer customer = new Customer(customerID);
			CustomerParty party = new CustomerParty();
			party.addCustomer(customer);
			systemInterface.createOrders(orders, customer, party); //replace with appropriately generated customerID
			customerID++;
			return;

		}
		for (SeatingStrategy value : SeatingStrategy.values()) {
			if (value.toString().equals(command)) {
				systemInterface.setSeatingStrategy(value);

				text.setText(command + " Strategy set");
			}
		}

		for( PrepStrategy value: PrepStrategy.values()){
			if(value.toString().equals(command)){
				systemInterface.setPrepStrategy(value);
				text.setText(command + " Strategy set");
			}
		}

		for(SpecialOffer value : SpecialOffer.values()){
			if(value.toString().equals(command)){
				if(e.getSource() instanceof JCheckBoxMenuItem){
					//I guess we should be doing this through sysinterface->command but it's so easy to do it this way.
					value.setActive(((JCheckBoxMenuItem)e.getSource()).getState());
				}
			}
		}

		//Display Special Attribute Menu (couldn't check these through case statement)
		for (MenuSpecialAttribute value : MenuSpecialAttribute.values()) {
			if (value.toString().equals(command)) {
				text.setText(value + " Menu\n\n");
				displayStringArray(systemInterface.getSpecialAttributeMenu(value));
				return;
			}
		}
	}

	public void displayStringArray(ArrayList<String> toDisplay) {
		for (String s : toDisplay) {
			text.append(s + "\n\n");
		}
	}

	public static void main(String[] args) {
		//Schedule a job for the event-dispatching thread:
		//creating and showing this application's GUI.
		javax.swing.SwingUtilities.invokeLater(new Runnable() {
			public void run() {
				createAndShowGUI();
			}
		});
	}

	public void stateChanged(ChangeEvent e) {
		if (e.getSource() == s1) {
			JSpinner source = (JSpinner) e.getSource();

			SpinnerModel dataModel = source.getModel();
			if (dataModel instanceof SpinnerNumberModel) {
				this.sim.setSleepTime((int) dataModel.getValue());
			}
		}
		else if (e.getSource() == frequencySelect){
			JSpinner source = (JSpinner)e.getSource();
			sim.setFrequency((int)source.getModel().getValue());
		}
	}

	public void update(ObSubject o, String arg) {
		text.append("\n" + arg + "\n\n");
	}
}
